﻿using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using Microsoft.Win32;
using System.Diagnostics;
using System.Net.Http;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Linq;

namespace FloatingClock
{
	public partial class MainWindow : Window
	{
		private DispatcherTimer timer;
		private TimeSpan? lastSetTime;
		private const string NTP_SERVER = "pool.ntp.org";
		private readonly string[] BACKUP_NTP_SERVERS = new[] {
			"time.windows.com",
			"time.nist.gov",
			"time.google.com"
		};

		public MainWindow()
		{
			InitializeComponent();

			// 设置定时器更新时间显示
			timer = new DispatcherTimer();
			timer.Interval = TimeSpan.FromSeconds(1);
			timer.Tick += Timer_Tick;
			timer.Start();

			// 初始化时间显示
			UpdateTimeDisplay();
		}

		private void Timer_Tick(object sender, EventArgs e)
		{
			UpdateTimeDisplay();
		}

		private void UpdateTimeDisplay()
		{
			timeDisplay.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
		}

		private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{
			if (e.ChangedButton == MouseButton.Left)
			{
				DragMove();
			}
		}

		private void CloseButton_Click(object sender, RoutedEventArgs e)
		{
			Close();
		}

		private void ChangeTime_Click(object sender, RoutedEventArgs e)
		{
			var timeSetWindow = new TimeSetWindow(lastSetTime);
			timeSetWindow.Owner = this;
			if (timeSetWindow.ShowDialog() == true)
			{
				ProcessStartInfo startInfo = new ProcessStartInfo();
				startInfo.FileName = "cmd.exe";
				startInfo.Arguments = $"/c time {timeSetWindow.SelectedTime:HH:mm:ss} && date {timeSetWindow.SelectedTime:yyyy-MM-dd}";
				startInfo.Verb = "runas";
				startInfo.UseShellExecute = true;

				try
				{
					Process.Start(startInfo);
					lastSetTime = timeSetWindow.SelectedTime.TimeOfDay;
				}
				catch (Exception ex)
				{
					MessageBox.Show("设置时间失败：" + ex.Message);
				}
			}
		}

		private async void RestoreTime_Click(object sender, RoutedEventArgs e)
		{
			try
			{
				Mouse.OverrideCursor = Cursors.Wait;
				var accurateTime = await GetNetworkTime();

				ProcessStartInfo startInfo = new ProcessStartInfo();
				startInfo.FileName = "cmd.exe";
				startInfo.Arguments = $"/c time {accurateTime:HH:mm:ss} && date {accurateTime:yyyy-MM-dd}";
				startInfo.Verb = "runas";
				startInfo.UseShellExecute = true;

				Process.Start(startInfo);
				MessageBox.Show($"时间已恢复为网络时间：\n{accurateTime:yyyy-MM-dd HH:mm:ss}", "恢复成功");
			}
			catch (Exception ex)
			{
				MessageBox.Show($"恢复时间失败：{ex.Message}", "错误");
			}
			finally
			{
				Mouse.OverrideCursor = null;
			}
		}

		private async Task<DateTime> GetNetworkTime()
		{
			// NTP报文大小为48字节
			byte[] ntpData = new byte[48];
			ntpData[0] = 0x1B;

			foreach (var server in new[] { NTP_SERVER }.Concat(BACKUP_NTP_SERVERS))
			{
				try
				{
					IPAddress[] addresses = await Dns.GetHostAddressesAsync(server);

					using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
					{
						socket.ReceiveTimeout = 3000;

						await socket.ConnectAsync(addresses[0], 123);
						await socket.SendAsync(new ArraySegment<byte>(ntpData), SocketFlags.None);
						await socket.ReceiveAsync(new ArraySegment<byte>(ntpData), SocketFlags.None);

						socket.Close();

						ulong intPart = (ulong)ntpData[40] << 24 | (ulong)ntpData[41] << 16 | (ulong)ntpData[42] << 8 | ntpData[43];
						ulong fractPart = (ulong)ntpData[44] << 24 | (ulong)ntpData[45] << 16 | (ulong)ntpData[46] << 8 | ntpData[47];
						ulong milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);

						DateTime networkDateTime = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((long)milliseconds);
						return networkDateTime.ToLocalTime();
					}
				}
				catch (Exception ex)
				{
					Debug.WriteLine($"NTP服务器 {server} 连接失败: {ex.Message}");
					continue;
				}
			}

			// 如果所有NTP服务器都失败，尝试HTTP时间服务器
			try
			{
				using (var client = new HttpClient())
				{
					client.Timeout = TimeSpan.FromSeconds(5);
					var response = await client.GetAsync("http://worldtimeapi.org/api/timezone/Asia/Shanghai");
					var json = await response.Content.ReadAsStringAsync();
					var timeStr = json.Split("datetime\":\"")[1].Split('"')[0];
					return DateTime.Parse(timeStr).ToLocalTime();
				}
			}
			catch (Exception ex)
			{
				throw new Exception("无法获取网络时间，所有时间服务器均连接失败", ex);
			}
		}
	}
}